package com.zhuang.springbootredis.lock;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

import java.util.UUID;

public class RedisDistributedLock implements AutoCloseable {
    private final Jedis jedis;
    private final String lockKey;
    private final String lockValue;
    private final int expireTime; // 锁的过期时间（秒）

    public RedisDistributedLock(Jedis jedis, String lockKey, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
        this.lockValue = UUID.randomUUID().toString();
    }

    /**
     * 获取锁
     *
     * @param timeout 超时时间（毫秒）
     * @return 是否获取成功
     */
    public boolean acquire(long timeout) {
        long endTime = System.currentTimeMillis() + timeout;
        while (System.currentTimeMillis() < endTime) {
            // 使用SET命令的NX和EX选项原子性地获取锁
            // String result = jedis.set(lockKey, lockValue, "NX", "EX", expireTime);
            String result = jedis.set(lockKey, lockValue, SetParams.setParams().nx().ex(expireTime));
            if ("OK".equals(result)) {
                return true;
            }

            // 短暂休眠避免频繁重试
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }
        return false;
    }

    /**
     * 释放锁
     *
     * @return 是否释放成功
     */
    public boolean release() {
        // 使用Lua脚本保证原子性：先检查锁值是否匹配，再删除
        String script =
                "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                        "   return redis.call('del', KEYS[1]) " +
                        "else " +
                        "   return 0 " +
                        "end";
        Object result = jedis.eval(script, 1, lockKey, lockValue);
        return result.equals(1L);
    }

    @Override
    public void close() {
        release();
    }
}